# plugs/infoitem.py
#
#

""" information items .. keyword/description pairs """

__copyright__ = 'this file is in the public domain'

from ommbot.world import add_cmnd, add_rebefore, add_reafter, add_example, \
                         get_datadir, add_alias
from ommbot.persist import Persist
from ommbot.generic import lockdec
import thread
import os

infolock = thread.allocate_lock()

# create lock descriptor
locked = lockdec(infolock)

class Infoitems(Persist):

    """ information items """

    @locked
    def add(self, item, issue):
        """ add an item """
        item = item.lower()
        if self.data.has_key(item):
            self.data[item].append(issue)
        else:
            self.data[item] = [issue]
        self.save()

    @locked
    def addnosave(self, item, issue):
        """ add item but don't save """
        item = item.lower()
        if self.data.has_key(item):
            self.data[item].append(issue)
        else:
            self.data[item] = [issue]

    @locked
    def deltxt(self, item, txt):
        """ delete todo item with txt in it """
        got = 0
        if not self.data.has_key(item):
            return got
        for i in range(len(self.data[item])-1, -1, -1):
            if txt in self.data[item][i]:
                del self.data[item][i]
                got += 1
                break
        if got:
            self.save()
        return got

    @locked
    def delete(self, item, itemnr):
        """ delete item with nr from list """
        try:
            del self.data[item.lower()][int(itemnr)]
            self.save()
            return 1
        except IndexError:
            return 0
        except ValueError:
            return 0
        except KeyError:
            return 0

    def size(self):
        """ return number of items """
        return len(self.data)

info = Infoitems(get_datadir() + os.sep + 'infoitems')

if not info.data:
    info.data = {}

def handle_infosize(bot, ievent):
    """ info-size .. show number of information items """
    ievent.reply("we have %s infoitems" % info.size())

add_cmnd('info-size', handle_infosize, ['USER', 'WEB'])
add_example('info-size', 'show number of infoitems', 'info-size')

def handle_addinfoitem(bot, ievent):
    """ <keyword> = <description> .. add information item """
    try:
        (what, description) = ievent.groups
    except ValueError:
        ievent.reply('i need <item> <description>')
        return
    if len(description) < 3:
        ievent.reply('i need at least 3 chars for the description')
        return
    info.add(what, description)
    ievent.reply('%s added' % description)

add_rebefore(10, '^(.+?)\s+=\s+(.+)$', handle_addinfoitem, 'USER')
add_example('=', 'add description to item', 'dunk = top')

def handle_question(bot, ievent):
    """ <keyword>? .. ask for information item description """
    try:
        what = ievent.groups[0]
    except IndexError:
        ievent.reply('i need a argument')
        return
    what = what.strip().lower()
    try:
        infoitem = info.data[what]
    except KeyError:
        ievent.reply('no infoitems known for %s' % what)
        return
    result = ""
    for item in infoitem:
        try:
            result += "%s .. " % item
        except:
            pass
    if result:
        ievent.reply(result[:-4])
    else:
        ievent.reply('no %s found' % what)

add_reafter(10, '^(.+)\?$', handle_question, ['USER', 'WEB'])
add_reafter(10, '^\?(.+)$', handle_question, ['USER', 'WEB'])
add_example('?', 'show infoitems of <what>', '1) test? 2) ?test')

def handle_forget(bot, ievent):
    """ forget <keyword> <txttomatch> .. remove information item where \
        description matches txt given """
    if len(ievent.args) > 1:
        what = ' '.join(ievent.args[:-1])
        txt = ievent.args[-1]
    else:
        ievent.missing('<item> <txttomatch> (min 3 chars)')
        return
    if len(txt) < 3:
        ievent.reply('i need txt with at least 3 characters')
        return
    what = what.strip().lower()
    try:
        nrtimes = info.deltxt(what, txt)
    except KeyError:
        ievent.reply('no records matching %s found' % what)
        return
    if nrtimes:
        ievent.reply('item deleted')
    else:
        ievent.reply('delete %s of %s failed' % (txt, what))

add_cmnd('info-forget', handle_forget, ['FORGET', 'OPER'])
add_example('info-forget', 'forget <item> containing <txt>', 'info-forget \
dunk bla')
add_alias('forget', 'info-forget')

def handle_searchdescr(bot, ievent):
    """ info-sd <txttosearchfor> .. search information items descriptions """
    if not ievent.rest:
        ievent.missing('<item>')
        return
    else:
        what = ievent.rest
    what = what.strip().lower()
    result = ""
    for item, value in info.data.iteritems():
        for item2 in value:
            if item2.find(what) != -1:
                result += "[%s] %s .. " % (item, item2)
    if result:
        ievent.reply(result[:-4])
    else:
        ievent.reply('none found')

add_cmnd('info-sd', handle_searchdescr, ['USER', 'WEB'])
add_example('info-sd', 'info-sd <txt> ..  search description of \
             infoitems', 'info-sd http')
add_alias('sd', 'info-sd')
add_alias('sl','info-sd')

def handle_searchinfo(bot, ievent):
    """ info-si <txt> .. search information keywords """
    if not ievent.rest:
        ievent.missing('<txt>')
        return
    else:
        what = ievent.rest
    what = what.strip().lower()
    result = ""
    for item in info.data.keys():
        if item.find(what) != -1:
            result += "%s .. " % item
    if result:
        ievent.reply(result[:-4])
    else:
        ievent.reply('none found')

add_cmnd('info-si', handle_searchinfo, ['USER', 'WEB'])
add_example('info-si', 'info-si <txt> ..  search the infoitems keys', \
             'info-si test')
add_alias('si','info-si')
